(function (factory) {
    if ( typeof define === 'function' && define.amd ) {
        // AMD. Register as an anonymous module.
        define(['jquery'], factory);
    } else if (typeof exports === 'object') {
        // Node/CommonJS style for Browserify
        module.exports = factory;
    } else {
        // Browser globals
        factory(jQuery);
    }
}(function ($) {

    var toFix = ['wheel', 'mousewheel', 'DOMMouseScroll', 'MozMousePixelScroll'];
    var toBind = 'onwheel' in document || document.documentMode >= 9 ? ['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'];
    var lowestDelta, lowestDeltaXY;

    if ( $.event.fixHooks ) {
        for ( var i = toFix.length; i; ) {
            $.event.fixHooks[ toFix[--i] ] = $.event.mouseHooks;
        }
    }

    $.event.special.mousewheel = {
        setup: function() {
            if ( this.addEventListener ) {
                for ( var i = toBind.length; i; ) {
                    this.addEventListener( toBind[--i], handler, false );
                }
            } else {
                this.onmousewheel = handler;
            }
        },

        teardown: function() {
            if ( this.removeEventListener ) {
                for ( var i = toBind.length; i; ) {
                    this.removeEventListener( toBind[--i], handler, false );
                }
            } else {
                this.onmousewheel = null;
            }
        }
    };

    $.fn.extend({
        mousewheel: function(fn) {
            return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel");
        },

        unmousewheel: function(fn) {
            return this.unbind("mousewheel", fn);
        }
    });


    function handler(event) {
        var orgEvent = event || window.event,
            args = [].slice.call(arguments, 1),
            delta = 0,
            deltaX = 0,
            deltaY = 0,
            absDelta = 0,
            absDeltaXY = 0,
            fn;
        event = $.event.fix(orgEvent);
        event.type = "mousewheel";

        // Old school scrollwheel delta
        if ( orgEvent.wheelDelta ) { delta = orgEvent.wheelDelta; }
        if ( orgEvent.detail )     { delta = orgEvent.detail * -1; }

        // New school wheel delta (wheel event)
        if ( orgEvent.deltaY ) {
            deltaY = orgEvent.deltaY * -1;
            delta  = deltaY;
        }
        if ( orgEvent.deltaX ) {
            deltaX = orgEvent.deltaX;
            delta  = deltaX * -1;
        }

        // Webkit
        if ( orgEvent.wheelDeltaY !== undefined ) { deltaY = orgEvent.wheelDeltaY; }
        if ( orgEvent.wheelDeltaX !== undefined ) { deltaX = orgEvent.wheelDeltaX * -1; }

        // Look for lowest delta to normalize the delta values
        absDelta = Math.abs(delta);
        if ( !lowestDelta || absDelta < lowestDelta ) { lowestDelta = absDelta; }
        absDeltaXY = Math.max(Math.abs(deltaY), Math.abs(deltaX));
        if ( !lowestDeltaXY || absDeltaXY < lowestDeltaXY ) { lowestDeltaXY = absDeltaXY; }

        // Get a whole value for the deltas
        fn = delta > 0 ? 'floor' : 'ceil';
        delta  = Math[fn](delta / lowestDelta);
        deltaX = Math[fn](deltaX / lowestDeltaXY);
        deltaY = Math[fn](deltaY / lowestDeltaXY);

        // Add event and delta to the front of the arguments
        args.unshift(event, delta, deltaX, deltaY);

        return ($.event.dispatch || $.event.handle).apply(this, args);
    }

}));

/**
 * @preserve jquery.fullscreen 1.1.5
 * https://github.com/kayahr/jquery-fullscreen-plugin
 * Copyright (C) 2012-2013 Klaus Reimer <k@ailis.de>
 * Licensed under the MIT license
 * (See http://www.opensource.org/licenses/mit-license)
 */
 
(function() {

/**
 * Sets or gets the fullscreen state.
 * 
 * @param {boolean=} state
 *            True to enable fullscreen mode, false to disable it. If not
 *            specified then the current fullscreen state is returned.
 * @return {boolean|Element|jQuery|null}
 *            When querying the fullscreen state then the current fullscreen
 *            element (or true if browser doesn't support it) is returned
 *            when browser is currently in full screen mode. False is returned
 *            if browser is not in full screen mode. Null is returned if 
 *            browser doesn't support fullscreen mode at all. When setting 
 *            the fullscreen state then the current jQuery selection is 
 *            returned for chaining.
 * @this {jQuery}
 */
function fullScreen(state)
{
    var e, func, doc;
    
    // Do nothing when nothing was selected
    if (!this.length) return this;
    
    // We only use the first selected element because it doesn't make sense
    // to fullscreen multiple elements.
    e = (/** @type {Element} */ this[0]);
    
    // Find the real element and the document (Depends on whether the
    // document itself or a HTML element was selected)
    if (e.ownerDocument)
    {
        doc = e.ownerDocument;
    }
    else
    {
        doc = e;
        e = doc.documentElement;
    }
    
    // When no state was specified then return the current state.
    if (state == null)
    {
        // When fullscreen mode is not supported then return null
        if (!((/** @type {?Function} */ doc["exitFullscreen"])
            || (/** @type {?Function} */ doc["webkitExitFullscreen"])
            || (/** @type {?Function} */ doc["webkitCancelFullScreen"])
            || (/** @type {?Function} */ doc["msExitFullscreen"])
            || (/** @type {?Function} */ doc["mozCancelFullScreen"])))
        {
            return null;
        }
        
        // Check fullscreen state
        state = !!doc["fullscreenElement"]
            || !!doc["msFullscreenElement"]
            || !!doc["webkitIsFullScreen"]
            || !!doc["mozFullScreen"];
        if (!state) return state;
        
        // Return current fullscreen element or "true" if browser doesn't
        // support this
        return (/** @type {?Element} */ doc["fullscreenElement"])
            || (/** @type {?Element} */ doc["webkitFullscreenElement"])
            || (/** @type {?Element} */ doc["webkitCurrentFullScreenElement"])
            || (/** @type {?Element} */ doc["msFullscreenElement"])
            || (/** @type {?Element} */ doc["mozFullScreenElement"])
            || state;
    }
    
    // When state was specified then enter or exit fullscreen mode.
    if (state)
    {
        // Enter fullscreen
        func = (/** @type {?Function} */ e["requestFullscreen"])
            || (/** @type {?Function} */ e["webkitRequestFullscreen"])
            || (/** @type {?Function} */ e["webkitRequestFullScreen"])
            || (/** @type {?Function} */ e["msRequestFullscreen"])
            || (/** @type {?Function} */ e["mozRequestFullScreen"]);
        if (func) 
        {
            func.call(e);
        }
        return this;
    }
    else
    {
        // Exit fullscreen
        func = (/** @type {?Function} */ doc["exitFullscreen"])
            || (/** @type {?Function} */ doc["webkitExitFullscreen"])
            || (/** @type {?Function} */ doc["webkitCancelFullScreen"])
            || (/** @type {?Function} */ doc["msExitFullscreen"])
            || (/** @type {?Function} */ doc["mozCancelFullScreen"]);
        if (func) func.call(doc);
        return this;
    }
}

/**
 * Toggles the fullscreen mode.
 * 
 * @return {!jQuery}
 *            The jQuery selection for chaining.
 * @this {jQuery}
 */
function toggleFullScreen()
{
    return (/** @type {!jQuery} */ fullScreen.call(this, 
        !fullScreen.call(this)));
}

/**
 * Handles the browser-specific fullscreenchange event and triggers
 * a jquery event for it.
 *
 * @param {?Event} event
 *            The fullscreenchange event.
 */
function fullScreenChangeHandler(event)
{
    jQuery(document).trigger(new jQuery.Event("fullscreenchange"));
}

/**
 * Handles the browser-specific fullscreenerror event and triggers
 * a jquery event for it.
 *
 * @param {?Event} event
 *            The fullscreenerror event.
 */
function fullScreenErrorHandler(event)
{
    jQuery(document).trigger(new jQuery.Event("fullscreenerror"));
}

/**
 * Installs the fullscreenchange event handler.
 */
function installFullScreenHandlers()
{
    var e, change, error;
    
    // Determine event name
    e = document;
    if (e["webkitCancelFullScreen"])
    {
        change = "webkitfullscreenchange";
        error = "webkitfullscreenerror";
    }
    else if (e["msExitFullscreen"])
    {
        change = "MSFullscreenChange";
        error = "MSFullscreenError";
    }
    else if (e["mozCancelFullScreen"])
    {
        change = "mozfullscreenchange";
        error = "mozfullscreenerror";
    }
    else 
    {
        change = "fullscreenchange";
        error = "fullscreenerror";
    }

    // Install the event handlers
    jQuery(document).bind(change, fullScreenChangeHandler);
    jQuery(document).bind(error, fullScreenErrorHandler);
}

jQuery.fn["fullScreen"] = fullScreen;
jQuery.fn["toggleFullScreen"] = toggleFullScreen;
installFullScreenHandlers();

})();

$(document).ready(function(){
    
    $("#resolution").html(screen.width+"x"+screen.height+"x"+screen.colorDepth);
    $("#bodysize").html($("#welcome").width()+"x"+$("#welcome").height());

    slide = new Array();
    current_slide = 0;
    var lock = 1;
            
    $("#main li").each(function(i){
        var id = $(this).attr("id");
        var title = $(this).data("title");
        var size = slide.push({
            "id" : id,
            "title" : title,
            "description" : $(this).data("desc"),
        });
        $("#control_buttons").append(
            $("<a />").attr("id", "btn-"+id).text(title).click(function(){go(size-1);})
        );
    });
    
    var adjust_control = function () {
        var $btn = $("#btn-"+slide[current_slide].id);
        var current_left = $btn.offset().left;
        var target_left  = ($("#container").width()-$btn.width())/2;
        var $wrapper = $("#control_buttons");
        var pos = $wrapper.position();
        pos.left += target_left-current_left;
        $wrapper.css("left", pos.left);
    }
        
    go = function(i) {
        if (slide.length>0 && i>=0 && i<slide.length) {
            // location.hash = slide[i].id;
            current_slide = i;
            $("#control .top .title").text(slide[i].title);
            $("#control .top .description").text(slide[i].description);
            $(".slide").addClass("hide");
            $("#" + slide[current_slide].id).removeClass("hide");
        }
        setTimeout(function(){lock=(i==0);}, 100);
        adjust_control();
    }
    
    $("#main").bind("mousewheel", function(e, d) {
        if (lock) return;
        if (d>0) { // wheel up
            go(current_slide-1);
        } else { // wheel down
            go(current_slide+1);
        }
    }).bind("click", function(e) {
        if (lock) return;
        if (current_slide + 1 == slide.length) {
            $(document).fullScreen(false);
            go(0);
        } else {
            go(current_slide+1);
        }
    });
    
    $(document).keyup(function(e) {
        if (lock) return;
        switch (e.keyCode) {
            case 37: // arrow left
                go(current_slide-1); break;
            case 39: // arror right
            case 13: // enter
            case 32: // space
                go(current_slide+1); break;
            case 27: // esc
                $(document).fullScreen(false);
                go(0);
        }
    });
    
    var mouse_in_control_panel = 0;
    var last_main_mousemove = 0;
    var control_panel_daemon = 0;
    
    $("#main").bind("mousemove", function () {
        if (slide[current_slide].id.substring(0,5) == "test-") {
            last_main_mousemove = $.now();
            $("#control").removeClass("control_hide").addClass("control_show");
            if (control_panel_daemon == 0) {
                control_panel_daemon = setInterval(function(){
                    if (!mouse_in_control_panel && $.now()-last_main_mousemove > 2000) {
                        $("#control").removeClass("control_show").addClass("control_hide");
                        clearInterval(control_panel_daemon);
                        control_panel_daemon = 0;
                    }
                }, 200);
            }
        }
    });

    $("#control").mouseenter(function(){
        mouse_in_control_panel = 1;
    }).mouseleave(function(){
        mouse_in_control_panel = 0;
    });

    var last_resize = 0;
    var resolution_tips_daemon = 0;
    $(window).resize(function(e) {
        $("#resolution").html(screen.width+"x"+screen.height+"x"+screen.colorDepth);
        $("#bodysize").html($("#welcome").width()+"x"+$("#welcome").height());
        $("#resolution_tips").text($("#body").width()+"x"+$("#container").height()).show();
        last_resize = $.now();
        if (resolution_tips_daemon == 0) {
            resolution_tips_daemon = setInterval(function(){
                if ($.now()-last_resize > 1000) {
                    $("#resolution_tips").fadeOut();
                    clearInterval(resolution_tips_daemon);
                    resolution_tips_daemon = 0;
                }
            }, 200);
        }
        adjust_control();
    }); 

    $("#start").click(function(){
        $(document).fullScreen(true);
        go(1);
    });

    $("#stop").click(function(){
        $(document).fullScreen(false);
        go(0);
    });

    go(0);
    
});
